package com.warom.sdg.util;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.ghgande.j2mod.modbus.ModbusException;
import com.ghgande.j2mod.modbus.io.ModbusTCPTransaction;
import com.ghgande.j2mod.modbus.msg.ModbusRequest;
import com.ghgande.j2mod.modbus.msg.ModbusResponse;
import com.ghgande.j2mod.modbus.msg.ReadCoilsRequest;
import com.ghgande.j2mod.modbus.msg.ReadCoilsResponse;
import com.ghgande.j2mod.modbus.msg.ReadInputDiscretesRequest;
import com.ghgande.j2mod.modbus.msg.ReadInputDiscretesResponse;
import com.ghgande.j2mod.modbus.msg.ReadInputRegistersRequest;
import com.ghgande.j2mod.modbus.msg.ReadInputRegistersResponse;
import com.ghgande.j2mod.modbus.msg.ReadMultipleRegistersRequest;
import com.ghgande.j2mod.modbus.msg.ReadMultipleRegistersResponse;
import com.ghgande.j2mod.modbus.msg.WriteCoilRequest;
import com.ghgande.j2mod.modbus.msg.WriteMultipleCoilsRequest;
import com.ghgande.j2mod.modbus.msg.WriteMultipleRegistersRequest;
import com.ghgande.j2mod.modbus.msg.WriteSingleRegisterRequest;
import com.ghgande.j2mod.modbus.net.TCPMasterConnection;
import com.ghgande.j2mod.modbus.procimg.SimpleRegister;
import com.ghgande.j2mod.modbus.util.BitVector;
import com.warom.sdg.callback.ConnectionListener;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Arrays;

/**
 * Modbus TCP 客户端工具类
 * 实现与PLC设备的TCP通信
 */
public class ModbusTcpClient {
    private static final String TAG = "ModbusTcpClient";
    
    private TCPMasterConnection connection;
    private ModbusTCPTransaction transaction;
    private String ipAddress;
    private int port;
    private int timeout = 5000; // 默认超时5秒
    private boolean connected = false;
    private int unitId = 1; // 默认单元ID
    
    // 断线重连相关
    private static final int DEFAULT_RECONNECT_INTERVAL = 5000; // 默认重连间隔5秒
    private int reconnectInterval = DEFAULT_RECONNECT_INTERVAL;
    private int maxReconnectAttempts = 10; // 最大重连尝试次数，-1表示无限重连
    private int reconnectAttempts = 0;
    private Handler reconnectHandler;
    private AtomicBoolean isReconnecting = new AtomicBoolean(false);
    private boolean autoReconnect = false;
    private ConnectionListener connectionListener;
    
    // PLC地址定义 - 使用参考地址
    private static final int REG_DEVICE_STATUS = 40100;
    private static final int REG_TEMPERATURE = 31000; 
    private static final int COIL_START_SWITCH = 200;

    /**
     * 连接状态监听接口
     */
    public interface ConnectionListener {
        /**
         * 连接成功回调
         */
        void onConnected();
        
        /**
         * 连接断开回调
         * @param reason 断开原因
         */
        void onDisconnected(String reason);
        
        /**
         * 重连尝试回调
         * @param attemptCount 当前尝试次数
         */
        void onReconnecting(int attemptCount);
        
        /**
         * 重连失败回调，达到最大尝试次数后调用
         */
        void onReconnectFailed();
    }

    /**
     * 构造函数
     * @param ipAddress PLC的IP地址
     * @param port 端口号，默认为502
     */
    public ModbusTcpClient(String ipAddress, int port) {
        this.ipAddress = ipAddress;
        this.port = port;
        reconnectHandler = new Handler(Looper.getMainLooper());
    }

    /**
     * 构造函数
     * @param ipAddress PLC的IP地址
     * @param port 端口号
     * @param unitId 单元ID
     */
    public ModbusTcpClient(String ipAddress, int port, int unitId) {
        this(ipAddress, port);
        this.unitId = unitId;
    }

    /**
     * 构造函数，使用默认端口502
     * @param ipAddress PLC的IP地址
     */
    public ModbusTcpClient(String ipAddress) {
        this(ipAddress, 502); // Modbus TCP默认端口是502
    }

    /**
     * 设置连接超时时间
     * @param timeout 超时时间（毫秒）
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * 设置连接状态监听器
     * @param listener 连接状态监听器
     */
    public void setConnectionListener(ConnectionListener listener) {
        this.connectionListener = listener;
    }
    
    /**
     * 设置是否自动重连
     * @param autoReconnect 是否自动重连
     */
    public void setAutoReconnect(boolean autoReconnect) {
        this.autoReconnect = autoReconnect;
    }
    
    /**
     * 设置重连间隔时间
     * @param intervalMs 间隔时间(毫秒)
     */
    public void setReconnectInterval(int intervalMs) {
        this.reconnectInterval = intervalMs;
    }
    
    /**
     * 设置最大重连尝试次数
     * @param maxAttempts 最大尝试次数，-1表示无限重连
     */
    public void setMaxReconnectAttempts(int maxAttempts) {
        this.maxReconnectAttempts = maxAttempts;
    }

    /**
     * 连接到PLC设备
     * @return 连接是否成功
     */
    public boolean connect() {
        // 在后台线程中执行网络操作，避免NetworkOnMainThreadException
        final boolean[] result = new boolean[1];
        final Object lock = new Object();
        
        Thread connectThread = new Thread(() -> {
            try {
                synchronized(lock) {
                    try {
                        // 关闭之前的连接
                        if (connection != null && connection.isConnected()) {
                            connection.close();
                        }
                        
                        // 确保J2mod库的兼容性修复已初始化
                        com.warom.sdg.util.J2modFix.init();
                        
                        // 创建新连接
                        InetAddress addr = InetAddress.getByName(ipAddress);
                        connection = new TCPMasterConnection(addr);
                        connection.setPort(port);
                        connection.setTimeout(timeout);
                        connection.connect();
                        
                        // 初始化事务
                        transaction = new ModbusTCPTransaction(connection);
                        // 设置重试次数为2次
                        transaction.setRetries(2);
                        
                        // 不再尝试设置retryDelayMillis字段，它在当前j2mod版本中不存在
                        
                        connected = true;
                        reconnectAttempts = 0; // 重置重连计数
                        
                        Log.d(TAG, "连接成功: " + ipAddress + ":" + port);
                        
                        // 操作成功
                        result[0] = true;
                    } catch (UnknownHostException e) {
                        String reason = "无法解析主机名: " + ipAddress;
                        Log.e(TAG, reason, e);
                        
                        // 通知UI线程处理失败
                        final String finalReason = reason;
                        if (Looper.myLooper() != Looper.getMainLooper()) {
                            new Handler(Looper.getMainLooper()).post(() -> 
                                handleConnectionFailure(finalReason));
                        } else {
                            handleConnectionFailure(finalReason);
                        }
                    } catch (Exception e) {
                        String reason = "连接失败: " + e.getMessage();
                        Log.e(TAG, reason, e);
                        
                        // 通知UI线程处理失败
                        final String finalReason = reason;
                        if (Looper.myLooper() != Looper.getMainLooper()) {
                            new Handler(Looper.getMainLooper()).post(() -> 
                                handleConnectionFailure(finalReason));
                        } else {
                            handleConnectionFailure(finalReason);
                        }
                    }
                    
                    // 通知等待的线程继续执行
                    lock.notifyAll();
                }
            } catch (Exception e) {
                Log.e(TAG, "连接线程异常", e);
                synchronized(lock) {
                    connected = false;
                    result[0] = false;
                    lock.notifyAll();
                }
            }
        });
        
        // 启动连接线程
        connectThread.start();
        
        // 同步等待连接完成
        try {
            synchronized(lock) {
                // 等待连接完成，最多等待timeout毫秒
                lock.wait(timeout + 1000);
            }
        } catch (InterruptedException e) {
            Log.e(TAG, "等待连接被中断", e);
            connected = false;
            return false;
        }
        
        // 如果连接成功且在主线程，调用连接成功回调
        if (result[0] && connectionListener != null) {
            new Handler(Looper.getMainLooper()).post(() -> {
                connectionListener.onConnected();
            });
        }
        
        return result[0];
    }

    /**
     * 断开与PLC的连接
     * @param reason 断开原因，用于日志记录
     */
    public void disconnect(String reason) {
        if (connection != null && connection.isConnected()) {
            Log.d(TAG, "连接断开: " + reason);
            connection.close();
            
            // 通知断开连接
            if (connectionListener != null) {
                connectionListener.onDisconnected(reason);
            }
        }
        connected = false;
        
        // 停止所有重连任务
        stopReconnecting();
    }
    
    /**
     * 断开与PLC的连接（无原因）
     */
    public void disconnect() {
        disconnect("主动断开连接");
    }
    
    /**
     * 保持连接活跃，如果连接断开则尝试重连
     * @return 连接是否正常
     */
    public boolean keepAlive() {
        if (!isConnected() && autoReconnect) {
            Log.d(TAG, "保持连接检测到连接已断开，尝试重连");
            return safeReconnect();
        }
        return isConnected();
    }
    
    /**
     * 开始自动重连
     * @param reason 连接断开原因
     */
    private void startReconnecting(final String reason) {
        // 如果已经在重连中，则不再启动新的重连
        if (isReconnecting.getAndSet(true)) {
            return;
        }

        reconnectAttempts = 0;
        
        // 定义重连任务
        Runnable reconnectRunnable = new Runnable() {
            @Override
            public void run() {
                if (!isReconnecting.get()) {
                    return; // 如果标志被重置，不再继续重连
                }
                
                reconnectAttempts++;
                
                // 通知正在重连
                if (connectionListener != null) {
                    connectionListener.onReconnecting(reconnectAttempts);
                }
                
                Log.d(TAG, "尝试重连 #" + reconnectAttempts + " 原因: " + reason);
                
                // 在后台线程中执行连接操作
                new Thread(() -> {
                    boolean connectResult = connect();
                    
                    // 在主线程中处理连接结果
                    new Handler(Looper.getMainLooper()).post(() -> {
                        if (connectResult) {
                            // 连接成功，停止重连
                            isReconnecting.set(false);
                            Log.d(TAG, "重连成功");
                        } else {
                            // 连接失败，判断是否继续重连
                            if (maxReconnectAttempts == -1 || reconnectAttempts < maxReconnectAttempts) {
                                // 继续重连
                                reconnectHandler.postDelayed(this, reconnectInterval);
                            } else {
                                // 达到最大重连次数，停止重连
                                Log.d(TAG, "达到最大重连次数，停止重连");
                                isReconnecting.set(false);
                                
                                // 通知重连失败
                                if (connectionListener != null) {
                                    connectionListener.onReconnectFailed();
                                }
                            }
                        }
                    });
                }).start();
            }
        };
        
        // 启动重连任务
        reconnectHandler.postDelayed(reconnectRunnable, reconnectInterval);
    }
    
    /**
     * 停止自动重连
     */
    public void stopReconnecting() {
        isReconnecting.set(false);
        reconnectHandler.removeCallbacksAndMessages(null);
    }
    
    /**
     * 手动重连
     * @return 重连是否启动成功
     */
    public boolean reconnect() {
        if (isReconnecting.get()) {
            Log.d(TAG, "已经在重连中");
            return false;
        }
        
        Log.d(TAG, "手动启动重连");
        startReconnecting("手动重连");
        return true;
    }
    
    /**
     * 处理连接失败
     * @param reason 失败原因
     */
    private void handleConnectionFailure(String reason) {
        // 确保连接标记为断开
        connected = false;
        
        // 通知连接断开
        if (connectionListener != null) {
            connectionListener.onDisconnected(reason);
        }
        
        // 如果开启了自动重连，则启动重连
        if (autoReconnect) {
            startReconnecting(reason);
        }
    }

    /**
     * 检查连接状态
     * @return 是否已连接
     */
    public boolean isConnected() {
        // 检查连接对象和连接状态标志
        boolean connectionValid = connection != null && connection.isConnected();
        
        // 如果标志和实际状态不一致，更新标志
        if (connected != connectionValid) {
            if (connected) {
                // 标志为连接但实际已断开
                Log.w(TAG, "发现连接实际已断开但标志仍为连接状态，更新标志");
                connected = false;
            } else {
                // 标志为断开但实际已连接
                Log.d(TAG, "发现连接仍然有效但标志为断开状态，更新标志");
                connected = true;
            }
        }
        
        return connected;
    }
    
    /**
     * 检查是否正在重连中
     * @return 是否正在重连
     */
    public boolean isReconnecting() {
        return isReconnecting.get();
    }

    /**
     * 执行Modbus请求
     * @param request Modbus请求
     * @return Modbus响应
     * @throws ModbusException 如果请求失败
     */
    private ModbusResponse executeRequest(ModbusRequest request) throws ModbusException {
        if (!isConnected()) {
            if (autoReconnect && !isReconnecting.get()) {
                // 如果设置了自动重连并且当前没有在重连，尝试重新连接
                Log.d(TAG, "连接已断开，尝试重新连接");
                if (safeReconnect()) {
                    Log.d(TAG, "重新连接成功，继续执行请求");
                } else {
                    throw new ModbusException("未连接到PLC，重连失败");
                }
            } else {
                throw new ModbusException("未连接到PLC");
            }
        }
        
        // 检查是否在主线程上
        if (Looper.myLooper() == Looper.getMainLooper()) {
            Log.w(TAG, "executeRequest被从主线程调用，这可能导致NetworkOnMainThreadException");
            
            // 使用同步机制在后台线程执行并等待结果
            final ModbusResponse[] response = new ModbusResponse[1];
            final ModbusException[] exception = new ModbusException[1];
            final Object lock = new Object();
            
            Thread executionThread = new Thread(() -> {
                try {
                    synchronized(lock) {
                        try {
                            transaction.setRequest(request);
                            // 在后台线程执行
                            executeRequestWithRetry(transaction);
                            response[0] = transaction.getResponse();
                        } catch (ModbusException e) {
                            exception[0] = e;
                        }
                        lock.notifyAll();
                    }
                } catch (Exception e) {
                    Log.e(TAG, "执行请求线程异常", e);
                    synchronized(lock) {
                        if (exception[0] == null) {
                            exception[0] = new ModbusException("执行请求发生异常: " + e.getMessage());
                        }
                        lock.notifyAll();
                    }
                }
            });
            
            executionThread.start();
            
            try {
                synchronized(lock) {
                    // 等待执行完成，最多等待timeout毫秒
                    lock.wait(timeout * 2);
                }
            } catch (InterruptedException e) {
                throw new ModbusException("等待Modbus请求执行被中断");
            }
            
            if (exception[0] != null) {
                throw exception[0];
            }
            
            if (response[0] == null) {
                throw new ModbusException("Modbus请求执行超时");
            }
            
            return response[0];
        } else {
            // 已经在后台线程，可以直接执行
            transaction.setRequest(request);
            return executeRequestWithRetry(transaction);
        }
    }
    
    /**
     * 执行带有重试机制的Modbus请求
     * @param transaction 要执行的Modbus事务
     * @return Modbus响应
     * @throws ModbusException 如果请求失败
     */
    private ModbusResponse executeRequestWithRetry(ModbusTCPTransaction transaction) throws ModbusException {
        int maxRetries = 3;
        int currentRetry = 0;
        ModbusException lastException = null;
        
        // 禁用内部重试机制，由我们自己管理重试
        transaction.setRetries(0);
        
        // 检查连接状态
        if (!isConnected()) {
            Log.w(TAG, "执行请求前发现连接已断开，尝试重连");
            if (!safeReconnect()) {
                throw new ModbusException("执行请求前重连失败");
            }
            // 重连成功后需要重新创建事务
            ModbusRequest savedRequest = transaction.getRequest();
            transaction = new ModbusTCPTransaction(connection);
            transaction.setRequest(savedRequest);
            transaction.setRetries(0);
        }
        
        while (currentRetry <= maxRetries) {
            try {
                if (currentRetry > 0) {
                    // 指数退避延迟: 500ms, 1000ms, 2000ms
                    long delayMs = 500 * (long)Math.pow(2, currentRetry - 1);
                    Log.d(TAG, "重试请求，延迟 " + delayMs + "ms，尝试 #" + (currentRetry + 1));
                    try {
                        Thread.sleep(delayMs);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                    }
                    
                    // 每次重试前检查连接状态
                    if (!isConnected()) {
                        Log.w(TAG, "重试前发现连接已断开，尝试重连");
                        if (!safeReconnect()) {
                            throw new ModbusException("重试过程中重连失败");
                        }
                        // 重连成功后需要重新创建事务
                        ModbusRequest savedRequest = transaction.getRequest();
                        transaction = new ModbusTCPTransaction(connection);
                        transaction.setRequest(savedRequest);
                        transaction.setRetries(0);
                    }
                }
                
                Log.d(TAG, "执行Modbus请求: " + transaction.getRequest().getHexMessage());
                transaction.execute();
                ModbusResponse response = transaction.getResponse();
                Log.d(TAG, "收到Modbus响应: " + (response != null ? response.getHexMessage() : "null"));
                return response;
            } catch (ModbusException e) {
                lastException = e;
                Log.e(TAG, "Modbus请求失败: " + e.getMessage(), e);
                
                // 判断是否是连接问题
                boolean isConnectionIssue = e.getMessage().contains("Connection") || 
                    e.getMessage().contains("connection") ||
                    e.getMessage().contains("Socket") ||
                    e.getMessage().contains("timed out");
                
                // 如果是连接问题，尝试重新连接
                if (isConnectionIssue && currentRetry < maxRetries) {
                    Log.w(TAG, "Modbus请求失败，可能是连接问题: " + e.getMessage() + "，尝试重新连接");
                    
                    // 使用安全的重连方法
                    if (safeReconnect()) {
                        // 重新创建事务
                        ModbusRequest savedRequest = transaction.getRequest();
                        transaction = new ModbusTCPTransaction(connection);
                        transaction.setRequest(savedRequest);
                        transaction.setRetries(0); // 禁用内部重试
                        Log.d(TAG, "重新连接成功，继续执行重试");
                    } else {
                        Log.e(TAG, "重新连接失败，无法继续执行请求");
                        handleConnectionFailure("Modbus请求过程中连接断开，重连失败: " + e.getMessage());
                        throw new ModbusException("Modbus请求失败，重连失败: " + e.getMessage());
                    }
                } else if (currentRetry >= maxRetries) {
                    Log.e(TAG, "Modbus请求执行失败，已达最大重试次数", e);
                    
                    if (isConnectionIssue) {
                        handleConnectionFailure("Modbus请求过程中连接断开: " + e.getMessage());
                    }
                    
                    throw e;
                }
                
                currentRetry++;
            }
        }
        
        throw lastException;
    }

    /**
     * 读取输入寄存器
     * @param address 起始地址
     * @param count 寄存器数量
     * @param unitId 设备单元ID
     * @return 读取的寄存器值数组
     * @throws ModbusException 如果读取失败
     */
    public int[] readInputRegisters(int address, int count, int unitId) throws ModbusException {
        ReadInputRegistersRequest request = new ReadInputRegistersRequest(address, count);
        request.setUnitID(unitId);
        
        ModbusResponse response = executeRequest(request);
        if (response instanceof ReadInputRegistersResponse) {
            ReadInputRegistersResponse readResponse = (ReadInputRegistersResponse) response;
            int[] values = new int[readResponse.getWordCount()];
            
            for (int i = 0; i < readResponse.getWordCount(); i++) {
                values[i] = readResponse.getRegisterValue(i);
            }
            return values;
        } else {
            throw new ModbusException("收到意外响应类型");
        }
    }
    
    /**
     * 读取输入寄存器并解析为浮点数
     * @param address 起始地址
     * @param count 寄存器数量 (必须是2的倍数，每个浮点数占用2个寄存器)
     * @return 解析后的浮点数值
     * @throws ModbusException 如果读取失败
     */
    public float readInputRegistersFloat(int address, int count) throws ModbusException {
        if (count != 2) {
            throw new IllegalArgumentException("浮点数读取必须指定2个寄存器");
        }
        
        // 使用默认单元ID读取
        int[] registers = readInputRegisters(address, count, unitId);
        
        // 将两个寄存器组合为一个浮点数（高位在前）
        int combined = (registers[0] << 16) | registers[1];
        return Float.intBitsToFloat(combined);
    }

    /**
     * 读取保持寄存器
     * @param address 起始地址
     * @param count 寄存器数量
     * @param unitId 设备单元ID
     * @return 读取的寄存器值数组
     * @throws ModbusException 如果读取失败
     */
    public int[] readHoldingRegisters(int address, int count, int unitId) throws ModbusException {
        Log.d(TAG, "开始读取保持寄存器: 地址=" + address + ", 数量=" + count + ", 单元ID=" + unitId);
        ReadMultipleRegistersRequest request = new ReadMultipleRegistersRequest(address, count);
        request.setUnitID(unitId);
        
        try {
            ModbusResponse response = executeRequest(request);
            if (response instanceof ReadMultipleRegistersResponse) {
                ReadMultipleRegistersResponse readResponse = (ReadMultipleRegistersResponse) response;
                int[] values = new int[readResponse.getWordCount()];
                
                for (int i = 0; i < readResponse.getWordCount(); i++) {
                    values[i] = readResponse.getRegisterValue(i);
                }
                Log.d(TAG, "保持寄存器读取成功: " + Arrays.toString(values));
                return values;
            } else {
                Log.e(TAG, "收到意外响应类型: " + response.getClass().getSimpleName());
                throw new ModbusException("收到意外响应类型");
            }
        } catch (ModbusException e) {
            Log.e(TAG, "读取保持寄存器失败: " + e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 读取线圈状态
     * @param address 起始地址
     * @param count 线圈数量
     * @param unitId 设备单元ID
     * @return 线圈状态数组
     * @throws ModbusException 如果读取失败
     */
    public boolean[] readCoils(int address, int count, int unitId) throws ModbusException {
        ReadCoilsRequest request = new ReadCoilsRequest(address, count);
        request.setUnitID(unitId);
        
        ModbusResponse response = executeRequest(request);
        if (response instanceof ReadCoilsResponse) {
            ReadCoilsResponse readResponse = (ReadCoilsResponse) response;
            boolean[] values = new boolean[readResponse.getBitCount()];
            
            for (int i = 0; i < readResponse.getBitCount(); i++) {
                values[i] = readResponse.getCoilStatus(i);
            }
            return values;
        } else {
            throw new ModbusException("收到意外响应类型");
        }
    }

    /**
     * 读取离散输入状态
     * @param address 起始地址
     * @param count 输入点数量
     * @param unitId 设备单元ID
     * @return 输入点状态数组
     * @throws ModbusException 如果读取失败
     */
    public boolean[] readDiscreteInputs(int address, int count, int unitId) throws ModbusException {
        ReadInputDiscretesRequest request = new ReadInputDiscretesRequest(address, count);
        request.setUnitID(unitId);
        
        ModbusResponse response = executeRequest(request);
        if (response instanceof ReadInputDiscretesResponse) {
            ReadInputDiscretesResponse readResponse = (ReadInputDiscretesResponse) response;
            boolean[] values = new boolean[readResponse.getBitCount()];
            
            for (int i = 0; i < readResponse.getBitCount(); i++) {
                values[i] = readResponse.getDiscreteStatus(i);
            }
            return values;
        } else {
            throw new ModbusException("收到意外响应类型");
        }
    }

    /**
     * 写入单个保持寄存器
     * @param address 寄存器地址
     * @param value 写入的值
     * @param unitId 设备单元ID
     * @return 是否写入成功
     * @throws ModbusException 如果写入失败
     */
    public boolean writeSingleRegister(int address, int value, int unitId) throws ModbusException {
        WriteSingleRegisterRequest request = new WriteSingleRegisterRequest(
                address, new SimpleRegister(value));
        request.setUnitID(unitId);
        
        executeRequest(request);
        return true;
    }

    /**
     * 写入多个保持寄存器
     * @param address 起始寄存器地址
     * @param values 写入的值数组
     * @param unitId 设备单元ID
     * @return 是否写入成功
     * @throws ModbusException 如果写入失败
     */
    public boolean writeMultipleRegisters(int address, int[] values, int unitId) throws ModbusException {
        SimpleRegister[] registers = new SimpleRegister[values.length];
        for (int i = 0; i < values.length; i++) {
            registers[i] = new SimpleRegister(values[i]);
        }
        
        WriteMultipleRegistersRequest request = new WriteMultipleRegistersRequest(address, registers);
        request.setUnitID(unitId);
        
        executeRequest(request);
        return true;
    }

    /**
     * 写入单个线圈
     * @param address 线圈地址
     * @param value 写入的值
     * @param unitId 设备单元ID
     * @return 是否写入成功
     * @throws ModbusException 如果写入失败
     */
    public boolean writeCoil(int address, boolean value, int unitId) throws ModbusException {
        WriteCoilRequest request = new WriteCoilRequest(address, value);
        request.setUnitID(unitId);
        
        executeRequest(request);
        return true;
    }

    /**
     * 写入多个线圈
     * @param address 起始线圈地址
     * @param values 写入的值数组
     * @param unitId 设备单元ID
     * @return 是否写入成功
     * @throws ModbusException 如果写入失败
     */
    public boolean writeMultipleCoils(int address, boolean[] values, int unitId) throws ModbusException {
        // 创建BitVector来存储线圈状态
        BitVector bitVector = new BitVector(values.length);
        
        // 设置每个线圈的状态
        for (int i = 0; i < values.length; i++) {
            bitVector.setBit(i, values[i]);
        }
        
        WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(address, bitVector);
        request.setUnitID(unitId);
        
        executeRequest(request);
        return true;
    }

    /**
     * 将参考地址转换为Modbus内部地址
     * @param referenceAddress 参考地址
     * @return Modbus内部地址
     */
    private int toModbusAddress(int referenceAddress) {
        if (referenceAddress >= 40001 && referenceAddress <= 49999) {
            // 保持寄存器
            return referenceAddress - 40001;
        } else if (referenceAddress >= 30001 && referenceAddress <= 39999) {
            // 输入寄存器
            return referenceAddress - 30001;
        } else if (referenceAddress >= 10001 && referenceAddress <= 19999) {
            // 离散输入
            return referenceAddress - 10001;
        } else if (referenceAddress >= 1 && referenceAddress <= 9999) {
            // 线圈
            return referenceAddress - 1;
        } else {
            throw new IllegalArgumentException("无效的Modbus参考地址: " + referenceAddress);
        }
    }
    
    /**
     * 将两个寄存器的值转换为IEEE 754浮点数
     * @param register1 第一个寄存器值
     * @param register2 第二个寄存器值
     * @return 浮点数值
     */
    public static float registersToFloat(int register1, int register2) {
        // 将两个16位寄存器合并为一个32位整数
        int combined = (register1 << 16) | register2;
        // 将32位整数解释为IEEE 754浮点数
        return Float.intBitsToFloat(combined);
    }
    
    /**
     * 将IEEE 754浮点数转换为两个寄存器值
     * @param floatValue 浮点数值
     * @return 包含两个寄存器值的数组(高16位在0，低16位在1)
     */
    public static int[] floatToRegisters(float floatValue) {
        // 将浮点数转换为32位整数
        int bits = Float.floatToIntBits(floatValue);
        // 拆分为两个16位整数
        int[] registers = new int[2];
        registers[0] = (bits >> 16) & 0xFFFF; // 高16位
        registers[1] = bits & 0xFFFF;         // 低16位
        return registers;
    }

    /**
     * 安全地尝试重新连接
     * 该方法包含完整的错误处理，并确保在后台线程执行
     * 
     * @return 是否重新连接成功
     */
    private boolean safeReconnect() {
        // 如果已经在重连中，等待重连结果
        if (isReconnecting.get()) {
            Log.d(TAG, "已经有重连过程在进行中，等待其完成");
            // 等待一段时间，看是否重连成功
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            return isConnected();
        }
        
        // 如果当前线程是主线程，需要在后台线程执行
        if (Looper.myLooper() == Looper.getMainLooper()) {
            final boolean[] result = new boolean[1];
            final Object lock = new Object();
            
            Thread reconnectThread = new Thread(() -> {
                synchronized(lock) {
                    result[0] = doReconnect();
                    lock.notifyAll();
                }
            });
            
            reconnectThread.start();
            
            try {
                synchronized(lock) {
                    lock.wait(timeout + 2000); // 等待重连完成
                }
            } catch (InterruptedException e) {
                Log.e(TAG, "等待重连被中断", e);
                return false;
            }
            
            return result[0];
        } else {
            // 在后台线程，直接执行重连
            return doReconnect();
        }
    }
    
    /**
     * 执行实际的重连操作
     * 注意：此方法应该在后台线程中调用
     * 
     * @return 是否重连成功
     */
    private boolean doReconnect() {
        if (isConnected()) {
            // 已经连接，不需要重连
            return true;
        }
        
        Log.d(TAG, "开始执行重连操作");
        try {
            disconnect("准备重新连接"); // 确保先断开，带有原因
            
            // 初始化重连标记
            isReconnecting.set(true);
            
            // 直接尝试连接
            boolean connected = connect();
            isReconnecting.set(false);
            
            return connected;
        } catch (Exception e) {
            Log.e(TAG, "重连过程发生异常: " + e.getMessage(), e);
            isReconnecting.set(false);
            return false;
        }
    }

    /**
     * 获取连接的IP地址
     * @return IP地址
     */
    public String getIpAddress() {
        return ipAddress;
    }
    
    /**
     * 获取连接的端口
     * @return 端口
     */
    public int getPort() {
        return port;
    }
} 